package com.masiyi.springsecuritydemo.config;

import com.masiyi.springsecuritydemo.handler.MyAuthenticationFailureHandler;
import com.masiyi.springsecuritydemo.handler.MyAuthenticationSuccessHandler;
import com.masiyi.springsecuritydemo.handler.MyLogoutSuccessHandler;
import com.masiyi.springsecuritydemo.metasource.CustomerSecurityMetaSource;
import com.masiyi.springsecuritydemo.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true, jsr250Enabled=true)
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {


    private FindByIndexNameSessionRepository sessionRepository;
    private CustomerSecurityMetaSource customSecurityMetadataSource;

    @Autowired
    @Lazy
    public void SecurityConfig(FindByIndexNameSessionRepository sessionRepository,
                               CustomerSecurityMetaSource customSecurityMetadataSource) {
        this.sessionRepository = sessionRepository;
        this.customSecurityMetadataSource = customSecurityMetadataSource;

    }

    /**
     * 这里有两种方式 authorizeHttpRequests 和 authorizeRequests
     *
     * @param http the {@link HttpSecurity} to modify
     * @throws Exception
     */
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.authorizeHttpRequests()
//                .mvcMatchers("/user/register").permitAll()
//                .mvcMatchers(HttpMethod.GET,"/admin").hasRole("ADMIN")  //具有 admin 角色   强大 通用: /admin /admin/  /admin.html
//                .mvcMatchers("/user").hasRole("USER")    //具有 user 角色
//                .mvcMatchers("/getInfo").hasAuthority("READ_INFO") //READ_INFO 权限
//                .antMatchers(HttpMethod.GET,"/admin").hasRole("ADMIN")
//                .anyRequest().authenticated()
//                .and().formLogin()
//                .successHandler(new MyAuthenticationSuccessHandler())
//                .failureHandler(new MyAuthenticationFailureHandler())
//                .and()
//                .logout().logoutSuccessHandler(new MyLogoutSuccessHandler())
//                .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
//                .and()
//                .cors() //跨域处理方案
//                .configurationSource(configurationSource())
//                .and()
//                .rememberMe() //开启记住我功能
//                .and()
//                .sessionManagement()  //开启会话管理
//                .maximumSessions(1)  //设置会话并发数为 1 在SessionRegistryImpl中管理key，key存的是对象，必须要重写User的equals和hashcode方法才能判断用户相等
//        ;
//    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //1.获取工厂对象
        ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
        //2.设置自定义 url 权限处理
        http.apply(new UrlAuthorizationConfigurer<>(applicationContext))
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setSecurityMetadataSource(customSecurityMetadataSource);
                        //是否拒绝公共资源访问
                        object.setRejectPublicInvocations(false);
                        return object;
                    }
                });
        http.formLogin().and().csrf().disable();
    }

    /**
     *允许所有来源的请求（*）使用任意的请求头和请求方法，并且设置了最大缓存时间为 3600 秒。
     * @return
     */
    CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
//
//    @Bean
//    public UserDetailsService userDetailsService() {
//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        inMemoryUserDetailsManager.createUser(User.withUsername("root").password("{noop}123").roles("ADMIN","USER").build());
//        inMemoryUserDetailsManager.createUser(User.withUsername("lisi").password("{noop}123").roles("USER").build());
//        inMemoryUserDetailsManager.createUser(User.withUsername("win7").password("{noop}123").authorities("READ_INFO").build());
//        return inMemoryUserDetailsManager;
//    }




    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry() {
        return new SpringSessionBackedSessionRegistry(sessionRepository);
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new MyUserDetailService();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
        auth.userDetailsService(userDetailsService());

    }
//
//    /**
//     * 指定加密方式
//     */
//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        // 使用BCrypt加密密码
//        return new BCryptPasswordEncoder();
//    }
}